package stickyhand;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.filter.ElementFilter;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class NZB {
	private boolean Validation = true;
	private File nzbFile = null;
	private Document nzbDoc;
	private LinkedList<NZBFile> fileList;
	private String name = null;
	private int msgId = 0;
	
	/**
	 * NZB - initialize the NZB object with a given file.
	 * @param nzbFile NZB xml file.
	 */
	public NZB(File nzbFile, boolean validate) throws IOException {
		fileList = new LinkedList<NZBFile>();
		this.setValidation(validate);
		this.setFile(nzbFile);
		this.setName(this.getFileName());
	}
	
	/**
	 * @return the validation
	 */
	public boolean getValidation() {
		return Validation;
	}

	/**
	 * @param validation the validation to set
	 */
	public void setValidation(boolean validation) {
		Validation = validation;
	}
	
	/**
	 * getName - get the human readable name of this NZB.
	 * @return the name of the NZB object.
	 */
	public String getFileName() {
		if (nzbFile == null)
			return null;
		return nzbFile.getName();
	}
	
	public LinkedList<NZBFile> getFileList() {
		return (LinkedList<NZBFile>)fileList.clone();
	}
	
	public String getName() {
		return name;
	}
	
	/**
	 * setName - Set or determine the human readable name of the NZB file.
	 */
	public void setName(String fileName) {
		StringBuilder result = new StringBuilder();
		fileName = fileName.replace("_", " ");
		StringTokenizer tok = new StringTokenizer(fileName, " ");
		
		if (tok.countTokens() < 3) {	/* looks like a non-standard file name. */
			result.append(fileName);
			name = result.toString();
			return;
		}
		
		/* standard msgid_1233445_Name_goes_here.nzb format. */
		if (tok.nextToken().equalsIgnoreCase("msgid") == false) {	/* bad format. */
			result.append(fileName);
			name = result.toString();
			return;
		}
		msgId = (new Integer(tok.nextToken())).intValue();
		
		while (tok.hasMoreTokens()) {
			String token = tok.nextToken();
			if (token.endsWith(".nzb")) {
				token = token.replace(".nzb", "");
			}
			result.append(token + " ");
		}
		name = result.toString();
		return;
	}
	
	public int getBytes() {
		Iterator files = fileList.iterator();
		int totalBytes = 0;
		
		while (files.hasNext()) {
			NZBFile file = (NZBFile)files.next();
			totalBytes += file.getBytes();
		}
		return totalBytes;
	}
	
	public int getNumFiles() {
		return fileList.size();
	}
	
	public int getNumSegments() {
		Iterator files = fileList.iterator();
		int totalSegs = 0;
		
		while (files.hasNext()) {
			NZBFile file = (NZBFile)files.next();
			totalSegs += file.getNumSegments();
		}
		return totalSegs;
	}
	
	private void parseNZBDoc() {
		Element rootElement = nzbDoc.getRootElement();
		Iterator elementList = rootElement.getDescendants(new ElementFilter("file"));
		while (elementList.hasNext()) {
			Element nextElement = (Element)elementList.next();
			List attributeList = nextElement.getAttributes();
			
			NZBFile file = new NZBFile(nextElement);
			fileList.add(file);
		}
	}
	
	public void setFile(File nzbFile) throws IOException {
		SAXBuilder builder;
		
		/* open and validate the NZB file. */
		builder = new SAXBuilder(this.getValidation());
		try {
			nzbDoc = builder.build(nzbFile);
		} catch (Exception e) {
			throw new IOException("Invalid NZB file");
		}
		this.nzbFile = nzbFile;		/* valid, so save. */
		
		/* gather the information from the DOM. */
		this.parseNZBDoc();
	}
	
	public void dumpNZB(OutputStream out) throws IOException {
		XMLOutputter fmt = new XMLOutputter();
		fmt.output(nzbDoc, out);
		return;
	}
	
	public static void main(String[] args) {
		String name = "msgid_2509588_The_Rosetta_Stone_-_Italian_[Level_1].nzb";
		
		File inputFile = new File(name);
		if (inputFile.exists() == false) {
			System.err.println("File does not exist: " + name);
			System.exit(1);
		}
		
		try {
			new NZB(inputFile, true);
		} catch (IOException e) {
			if (e.getMessage() != null)
				System.out.println(e.getMessage());
			else
				e.getStackTrace();
		}
	}
}
